package uk.co.tarbard.svnreporter.logentries;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

public class SVNLogRetriever implements ILogRetriever {

	SVNRepository repository = null;

	String url = null;

	private final String username;

	private final String password;

	public SVNLogRetriever(String username, String password, String url) {
		this.username = username;
		this.password = password;
		this.url = url;

		SVNRepositoryFactoryImpl.setup(); // for svn and svn+ssh connections.
	}

	public List<LogEntry> getLogEntries() {

		try {
			/*
			 * Creates an instance of SVNRepository to work with the repository.
			 * All user's requests to the repository are relative to the
			 * repository location used to create this SVNRepository. SVNURL is
			 * a wrapper for URL strings that refer to repository locations.
			 */
			repository = SVNRepositoryFactory.create(SVNURL.parseURIDecoded(url));
		} catch (SVNException svne) {
			System.err.println("error while creating an SVNRepository for the location - Malformed URL?'" + url + "': "
					+ svne.getMessage());
		}

		long startRevision = 0;
		long endRevision = -1;
		ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password);
		repository.setAuthenticationManager(authManager);

		/*
		 * Gets the latest revision number of the repository
		 */
		try {
			endRevision = repository.getLatestRevision();
		} catch (SVNException svne) {
			System.err.println("error while fetching the latest repository revision: " + svne.getMessage());
		}
		System.out.println(endRevision);

		Collection logEntries = null;
		try {
			/*
			 * Collects SVNLogEntry objects for all revisions in the range
			 * defined by its start and end points [startRevision, endRevision].
			 * For each revision commit information is represented by
			 * SVNLogEntry.
			 * 
			 * the 1st parameter (targetPaths - an array of path strings) is set
			 * when restricting the [startRevision, endRevision] range to only
			 * those revisions when the paths in targetPaths were changed.
			 * 
			 * the 2nd parameter if non-null - is a user's Collection that will
			 * be filled up with found SVNLogEntry objects; it's just another
			 * way to reach the scope.
			 * 
			 * startRevision, endRevision - to define a range of revisions you
			 * are interested in; by default in this program - startRevision=0,
			 * endRevision= the latest (HEAD) revision of the repository.
			 * 
			 * the 5th parameter - a boolean flag changedPath - if true then for
			 * each revision a corresponding SVNLogEntry will contain a map of
			 * all paths which were changed in that revision.
			 * 
			 * the 6th parameter - a boolean flag strictNode - if false and a
			 * changed path is a copy (branch) of an existing one in the
			 * repository then the history for its origin will be traversed; it
			 * means the history of changes of the target URL (and all that
			 * there's in that URL) will include the history of the origin
			 * path(s). Otherwise if strictNode is true then the origin path
			 * history won't be included.
			 * 
			 * The return value is a Collection filled up with SVNLogEntry
			 * Objects.
			 */
			logEntries = repository.log(new String[] { "" }, null, startRevision, endRevision, true, true);

		} catch (SVNException svne) {
			System.out.println("error while collecting log information for '" + url + "': " + svne.getMessage());
		}

		List<LogEntry> myLogEntries = new ArrayList<LogEntry>();
		for (Iterator iter = logEntries.iterator(); iter.hasNext();) {
			SVNLogEntry svnLogEntry = (SVNLogEntry) iter.next();
			myLogEntries.add(new LogEntry(svnLogEntry.getChangedPaths(), svnLogEntry.getRevision(), svnLogEntry.getAuthor(),
					svnLogEntry.getDate(), svnLogEntry.getMessage()));
		}

		return myLogEntries;
	}

}
